#include "StdAfx.h"
#include "Matrix44.h"
#include "Vector3.h"
#include "Quaternion.h"
#include "Plane.h"

VAMPIRE_NAMESPACE_BEGIN

Matrix44::Matrix44( Real m00, Real m01, Real m02, Real m03, Real m10, Real m11, Real m12, Real m13, Real m20, Real m21, Real m22, Real m23, Real m30, Real m31, Real m32, Real m33 )
{
	mData._11 = m00; mData._12 = m01; mData._13 = m02; mData._14 = m03;
	mData._21 = m10; mData._22 = m11; mData._23 = m12; mData._24 = m13;
	mData._31 = m20; mData._32 = m21; mData._33 = m22; mData._34 = m23;
	mData._41 = m30; mData._42 = m31; mData._43 = m32; mData._44 = m33;
}

Matrix44 Matrix44::operator + ( const Matrix44& rhs ) const
{
	return Matrix44(mData + rhs.mData);
}

Vampire::Matrix44 Matrix44::operator+() const
{
	return *this;
}

Vampire::Matrix44 Matrix44::operator * ( const Matrix44& rhs ) const
{
	return Matrix44(mData * rhs.mData); 
}

Vampire::Matrix44 Matrix44::operator*( const Real& rhs ) const
{
	return Matrix44(mData * rhs);
}

Vampire::Matrix44 Matrix44::operator - ( const Matrix44& rhs ) const
{
	return Matrix44(mData - rhs.mData); 
}

Vampire::Matrix44 Matrix44::operator / ( const Real& rhs ) const
{
	return Matrix44(mData / rhs);
}

Vampire::Matrix44& Matrix44::operator += ( const Matrix44& rhs )
{
	mData += rhs.mData;
	return *this;
}

Matrix44& Matrix44::operator-=( const Matrix44& rhs )
{
	mData -= rhs.mData;
	return *this;
}

Matrix44& Matrix44::operator*=( const Matrix44& rhs )
{
	mData *= rhs.mData;
	return *this;
}

Matrix44& Matrix44::operator*=( const Real& rhs )
{
	mData *= rhs;
	return *this;
}

Matrix44& Matrix44::operator/=( const Real& rhs )
{
	mData /= rhs;
	return *this;
}

void Matrix44::operator=( const Matrix44& rhs )
{
	mData = rhs.mData;
}

void Matrix44::operator=( const D3DXMATRIX& rhs )
{
	mData = rhs;
}

BOOL Matrix44::operator==( const Matrix44& rhs ) const
{
	return mData == rhs.mData ? TRUE : FALSE;
}

BOOL Matrix44::operator!=( const Matrix44& rhs ) const
{
	return mData == rhs.mData ? FALSE : TRUE;
}

Matrix44 Matrix44::operator-() const
{
	return Matrix44(-mData);
}

const Real* Matrix44::operator[]( const UINT& index ) const
{
	assert( index < 4 );
	return mData.m[index];
}

void Matrix44::decomposition( Vector3& scale, Quaternion& rotation, Vector3& translation ) const
{
	D3DXMatrixDecompose(&(scale.mData), &(rotation.mData), &(translation.mData), &mData);
}

Vampire::Real Matrix44::calculateDeterminantValue() const
{
	return D3DXMatrixDeterminant(&mData);
}

Vampire::Matrix44 Matrix44::getInverse() const
{
	Matrix44 inverse;
	Real det = calculateDeterminantValue();
	D3DXMatrixInverse(&(inverse.mData), &det, &mData);
	return inverse;
}

Matrix44 Matrix44::multiply( const Matrix44& m ) const
{
	Matrix44 result;
	D3DXMatrixMultiply(&(result.mData), &mData, &(m.mData));
	return result;
}

Vampire::Matrix44 Matrix44::crossThenTranspose( const Matrix44& m ) const
{
	Matrix44 result;
	D3DXMatrixMultiplyTranspose (&(result.mData), &mData, &(m.mData));
	return result;
}

void Matrix44::reflectToPlane( const Plane& plane )
{
	D3DXMatrixReflect(&mData, &(plane.mData));
}

void Matrix44::fromAngleAxis( const Real& angle, const Vector3& axis )
{
	D3DXMatrixRotationAxis(&mData, &(axis.mData), angle);
}

void Matrix44::fromQuat( const Quaternion& quat )
{
	D3DXMatrixRotationQuaternion(&mData, &(quat.mData));
}

void Matrix44::rotateAroundX( const Radian& angle )
{
	D3DXMatrixRotationX(&mData, angle.mData);
}

void Matrix44::rotateAroundY( const Radian& angle )
{
	D3DXMatrixRotationY(&mData, angle.mData);
}

void Matrix44::rotateAroundZ( const Radian& angle )
{
	D3DXMatrixRotationZ(&mData, angle.mData);
}

void Matrix44::rotateAllAxis( const Radian& x, const Radian& y, const Radian& z )
{
	D3DXMatrixRotationYawPitchRoll(&mData, y.mData, x.mData, z.mData);
}

void Matrix44::scale( const Real& sx, const Real& sy, const Real& sz )
{
	D3DXMatrixScaling(&mData, sx, sy, sz);
}

void Matrix44::scale( const Vector3& s )
{
	D3DXMatrixScaling(&mData, s.mData.x, s.mData.y, s.mData.z);
}

void Matrix44::translate( const Real& x, const Real& y, const Real& z )
{
	D3DXMatrixTranslation(&mData, x, y, z);
}

void Matrix44::translate( const Vector3& pos )
{
	D3DXMatrixTranslation(&mData, pos.mData.x, pos.mData.y, pos.mData.z);
}

Matrix44 Matrix44::getTranspose() const
{
	Matrix44 trans;
	D3DXMatrixTranspose(&(trans.mData), &mData);
	return trans;
}

Quaternion Matrix44::toQuat()
{
	Quaternion quat;
	D3DXQuaternionRotationMatrix(&(quat.mData), &mData);
	return quat;
}

void Matrix44::inverse()
{
	Real det = calculateDeterminantValue();
	D3DXMatrixInverse(&mData, &det, &mData);
}

void Matrix44::transpose()
{
	D3DXMatrixTranspose(&mData, &mData);
}

void Matrix44::rotate( const Quaternion& rotate )
{
	Matrix44 m(rotate);
	D3DXMatrixMultiply(&mData, &mData, &(m.mData));
}

const Matrix44 Matrix44::ZERO(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
const Matrix44 Matrix44::IDENTITY(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);

VAMPIRE_NAMESPACE_END